//
// Created by denglibin on 19-4-9.
//

/**
 * include <unistd.h>
    ssize_t read (int fd, void *buf, size_t len);
    该系统调用由fd指向的当前偏移量至多读取len个字节到buf中，成功将返回写入buf的字节数。出错时返回-1,并设置errno.
    fd所指向的文件位置将会向前移动，移动的长度由之前读取的字节数决定。
    达到文件末尾返回0;
    如果没数据可读（并不是读到末尾）则阻塞，如果以非阻塞（O_NONBLOCK）方式打开文件,无数据可读时直接返回-1，并设置errno为EAGAIN
 */

#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

/**
 * read测试
 * @return
 */
static int testRead(){
    ssize_t  ret;
    int len = 10;
    char buf[len + 1];//需要一个0结尾
    int fd;
    fd = open("/home/denglibin/open.txt", O_RDONLY|O_NONBLOCK, 0644); // 非阻塞
    if(fd == -1){
        perror("open");//打印 errno对应的错误信息
        return -1;
    }
    memset(buf, 0, len);
    while ((ret = read(fd, buf, len)) != 0){
        printf("%s\n", buf);//当成字符串打印，字符串是以0结尾的字符数组。（如果最后一个字符不是0，则可能多出现一个"?"）
        memset(buf, 0, len);
        if(ret == -1){
            if(errno == EINTR){ //调用返回-1并且errno被设置成EINTR。表示在读入之前收到了一个信号，可以重新进行调用
                continue;
            }
            if(errno == EAGAIN){ //非阻塞模式 没数据可读了 返回-1并且errno被设置成EAGAIN
                perror("无数据可读");
                break;
            }
            perror("read");
        }
    }
    printf("结束");
    close(fd);
}

/**
 * 复制图片
 * @return
 */
static int testCopyPic(){
    const int  buf_len = 1024;
    char buf[1024] = {0};
    int readFd = open("/home/denglibin/image/123.jpg", O_RDONLY, 0644); // 以读的方式打开文件
    if(readFd == -1){
        perror("open read");
        return -1;
    }
    int writeFd = open("/home/denglibin/image/234.jpg", O_WRONLY | O_CREAT | O_TRUNC, 0644); // 以写的方式打开文件，如果文件存在则清空，如果不存在则创建
    if(writeFd == -1){
        perror("open write");
        return -1;
    }
    int ret = 0; // 记录读取的字节数
    while ((ret = read(readFd, buf, buf_len)) != 0){  // =0表示读到文件末尾
        int writeLen = 0; // 记录写入的字节数
        char * startIndex = buf; // 记录写入数据的起始位置
        int  left = ret; // 缓冲区中剩余要写入的字节数
        while ((writeLen = write(writeFd, startIndex, left)) < left){  // write可能不能一次性把buf中的数据全部写入，所以循环写
            startIndex += writeLen;  // 移动写入的起始位置
            left -= writeLen; // 修改要写入的字节数
        }
    }
    close(readFd); // 关闭
    close(writeFd); // 关闭
}
 static int main_(){

    testCopyPic();
    return 0;
}